package com.jt.msg;

import com.jt.utils.BCD;
import com.jt.utils.JT808Const;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.ReferenceCountUtil;
import org.apache.commons.lang3.StringUtils;

/**
 * 数据报
 *
 * @author wang xiao
 * date 2023/8/9
 */
public class DataPacket {

    /**
     * 消息头
     */
    protected PacketHeader header = new PacketHeader();

    /**
     * 消息体
     */
    protected ByteBuf payload;

    public DataPacket() {
    }

    public DataPacket(ByteBuf payload) {
        this.payload = payload;
    }

    public void parse() {
        try {
            this.parseHead();
            //验证包体长度
            if (this.header.getMsgBodyLength() != this.payload.readableBytes()) {
                throw new RuntimeException("包体长度有误");
            }
            this.parseBody();
        } finally {
            ReferenceCountUtil.safeRelease(this.payload);
        }
    }

    protected void parseHead() {
        header.setMsgId(payload.readShort());
        header.setMsgBodyProps(payload.readShort());
        header.setTerminalId(BCD.BCDtoString(readBytes(6)));
        header.setFlowId(payload.readShort());
        if (header.hasSubPackage()) {
            //TODO 处理分包
            payload.readInt();
        }
    }

    /**
     * 请求报文重写
     */
    protected void parseBody() {

    }

    /**
     * 响应报文重写 并调用父类
     *
     * @return
     */
    public ByteBuf toByteBufMsg() {
        ByteBuf bb = ByteBufAllocator.DEFAULT.heapBuffer();//在JT808Encoder escape()方法处回收
        bb.writeInt(0);//先占4字节用来写msgId和msgBodyProps，JT808Encoder中覆盖回来
        bb.writeBytes(BCD.toBcdBytes(StringUtils.leftPad(this.header.getTerminalId(), 12, "")));
        bb.writeShort(this.header.getFlowId());
        //TODO 处理分包
        return bb;
    }

    /**
     * 从ByteBuf中read固定长度的数组,相当于ByteBuf.readBytes(byte[] dst)的简单封装
     *
     * @param length length of read bytes
     * @return buffer
     */
    public byte[] readBytes(int length) {
        byte[] bytes = new byte[length];
        this.payload.readBytes(bytes);
        return bytes;
    }

    /**
     * 从ByteBuf中读出固定长度的数组 ，根据808默认字符集构建字符串
     *
     * @param length length of read bytes
     * @return String
     */
    public String readString(int length) {
        return new String(readBytes(length), JT808Const.DEFAULT_CHARSET);
    }


    public PacketHeader getHeader() {
        return header;
    }

    public void setHeader(PacketHeader header) {
        this.header = header;
    }

    public ByteBuf getPayload() {
        return payload;
    }

    public void setPayload(ByteBuf payload) {
        this.payload = payload;
    }
}
